#include <concepts>
#include <coroutine>
#include <exception>
#include <iostream>
#include <chrono>
#include <thread>
using namespace std::chrono_literals;

struct ReturnObject
{
    struct promise_type
    {
        uint32_t value_;
        ReturnObject get_return_object()
        {
            return {
                .h_ = std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        std::suspend_never initial_suspend()
        {
            return {};
        }
        std::suspend_never final_suspend() noexcept
        {
            return {};
        }
        std::suspend_always yield_value(uint32_t value)
        {
            value_ = value;
            return {};
        }
        void unhandled_exception()
        {
        }
    };
    std::coroutine_handle<promise_type> h_;
};

[[nodiscard]] ReturnObject counter()
{
    for (uint32_t i = 0;; ++i)
    {
        std::cout << "before yield\n";
        // co_yield 等价于 co_await p.yield_value(i); 也就是先赋值再等待
        // 本例中p.yield_value返回值为std::suspend_always{}，因此总是会挂起协程
        co_yield i;
        std::cout << "after yield\n";
    }
}

void test1()
{
    auto h = counter().h_;
    auto &promise = h.promise();
    for (int i = 0; i < 3; ++i)
    {
        //由于协程已经启动，启动后首先会执行赋值然后挂起等待
        //此处的promise.value_是0
        std::cout << "p.v before h() " << promise.value_ << std::endl;
        h();
        //执行了协程后，counter内部经过co_yield挂起，回到for循环赋值为1
        std::cout << "p.v after h() " << promise.value_ << std::endl;
    }
    h.destroy();
}

int main(int argc, char **argv)
{
    test1();
    return 0;
}
